<template>
  <TrLayout
    v-model="popupValue"
    @close="closeHanlde"
    :width="1227"
    title="新增工艺路线"
    @confrim="confrimHandle"
  >
    <div class="route-content">
      <TrEdit
        v-model="formObj"
        :formData="formData"
        :list="popupList"
        ref="form"
      ></TrEdit>
      <div class="route-flow" ref="logicContainer"></div>
    </div>
    <TrEditPopup
      v-model="isShowEdit"
      :width="480"
      title="工序属性"
      :valueObj.sync="proFormObj"
      :formData="proFormData"
      :list="proPopupList"
      @close="isShowEdit = false"
      @load-label="changeLoadLabel"
      @confrim="confrimProductHandle"
    />

    <TrEditPopup
      v-model="isShowEdgeEdit"
      :width="480"
      title="条件判断"
      :valueObj.sync="edgeFormObj"
      :formData="edgeFormData"
      :list="edgePopupList"
      @close="isShowEdgeEdit = false"
      @confrim="confrimEdgeHandle"
    />
  </TrLayout>
</template>
<script>
import { Control, DndPanel, Menu, BpmnElement } from "@logicflow/extension";
import { createFlow } from "@/api/baseCode/processRoute";
import nodeCustom from "../js/nodeCustom";
import edgeCustom from "../js/edgeCustom";
import LogicFlow from "@logicflow/core";
import "@logicflow/core/lib/style/index.css";
import "@logicflow/extension/lib/style/index.css";
import TrLayout from "@/components/Tr-layout/Tr-layout.vue";
import TrEditPopup from "@/components/Tr-edit/Tr-edit-popup.vue";
import TrEdit from "@/components/Tr-edit/Tr-edit.vue";
import turboAdapter from "@/utils/turboAdapter";
export default {
  name: "routeFlowBox",
  props: {
    value: {
      type: Boolean,
      default: false,
    },
    workOrdTypeList: {
      type: Array,
      default: () => [],
    },
    detailData: {
      type: Object,
      default: () => {},
    },
    operaType: {
      type: String,
      default: "add",
    },
  },
  components: {
    TrLayout,
    TrEdit,
    TrEditPopup,
  },
  computed: {
    popupValue() {
      return this.value;
    },
  },
  watch: {
    value(newVal) {
      if (newVal) {
        this.initHandle();
        this.$nextTick(() => {
          this.initLfHandle();
        });
      }
    },
  },
  data: () => ({
    proFormObj: {},
    proFormData: {},
    proPopupList: [
      {
        label: "工序步骤",
        type: "input",
        width: 100,
        value: "",
        inputType: "number",
        id: "processStep",
      },
      {
        label: "工序名称",
        type: "loadselect",
        width: 100,
        selectedLabel: "",
        requestObj: {
          url: "/api/mes-production-service/process/page",
          method: "post",
          searchKey: "processName",
          rlLabel: "processName",
          rlValue: "id",
          resultKey: "data,data,records",
        },
        value: "",
        id: "processId",
      },
      {
        label: "工序类型",
        type: "select",
        width: 100,
        list: [
          {
            label: "必选工序",
            value: 10,
          },
          {
            label: "可选工序",
            value: 20,
          },
        ],
        value: "",
        id: "processType",
      },
    ],
    isShowEdit: false,
    isShowEdgeEdit: false,
    edgeFormObj: {},
    edgeFormData: {},
    edgePopupList: [
      // {
      //   label: "工序步骤",
      //   type: "input",
      //   width: 100,
      //   value: `status.equals("1")`,
      //   disabled: true,
      //   id: "conditionsequenceflow",
      // },
      {
        label: "采集结果",
        type: "select",
        width: 100,
        list: [
          {
            label: "OK",
            value: 1,
          },
          {
            label: "NG",
            value: 2,
          },
        ],
        value: "",
        id: "collectResult",
      },
    ],
    formData: {},
    formObj: {},
    popupList: [
      {
        label: "线路编码",
        type: "input",
        width: 25,
        value: "",
        id: "craftRouteCode",
      },
      {
        label: "线路名称",
        type: "input",
        width: 25,
        value: "",
        id: "craftRouteName",
      },
      {
        label: "线路类别",
        type: "select",
        width: 25,
        value: "",
        id: "craftRouteType",
        list: [],
      },
      {
        label: "版本号",
        type: "input",
        width: 25,
        value: "",
        id: "craftRouteVersion",
      },
      {
        label: "启动日期",
        type: "date",
        width: 25,
        value: "",
        id: "activeTime",
      },
      {
        label: "失效日期",
        type: "date",
        width: 25,
        value: "",
        id: "inactiveTime",
      },
      {
        label: "描述",
        type: "input",
        width: 25,
        value: "",
        id: "craftRouteRemark",
        isNeed: false,
      },
    ],
    lf: null,
    flowConfig: {
      stopZoomGraph: true, // 禁止缩放
      // 背景网格大小
      grid: {
        size: 10,
        type: "dot",
      },
      keyboard: {
        enabled: true,
      },
      snapline: true,
      edgeType: "bpmn:sequenceFlow",
    },
    flowNodes: [
      {
        type: "bpmn:startEvent",
        text: "开始",
        label: "开始节点",
        properties: {
          type: "start",
        },
        icon: "",
      },
      {
        type: "bpmn:userTask",
        label: "任务节点",
        properties: {
          type: "task",
          processStep: "",
          processId: "",
          processName: "",
          processType: "",
        },
        icon: "",
        className: "important-node",
      },
      {
        type: "bpmn:exclusiveGateway",
        label: "条件判断",
        icon: "",
      },
      {
        type: "bpmn:endEvent",
        text: "结束",
        label: "结束节点",
        properties: {
          type: "end",
        },
        icon: "",
      },
    ],
    loadLableObj: {},
  }),
  methods: {
    confrimEdgeHandle() {
      let propertiesObj = {
        conditionsequenceflow: this.edgeFormData.conditionsequenceflow,
        collectResult: this.edgeFormObj.collectResult,
        defaultConditions:
          this.edgeFormObj.collectResult == 1 ? "true" : "false",
        customError: false,
      };
      this.lf.setProperties(this.edgeFormData.id, propertiesObj);
      const edgeItem = this.lf.getEdgeModelById(this.edgeFormData.id);
      edgeItem.updateText(this.edgeFormObj.collectResult == 1 ? "OK" : "NG");
      this.isShowEdgeEdit = false;
    },
    createLf() {
      let that = this;
      this.lf = new LogicFlow({
        ...this.flowConfig,
        plugins: [Control, DndPanel, Menu, turboAdapter, BpmnElement],
        editable: false,
        container: this.$refs.logicContainer,
      });

      this.lf.register(nodeCustom);
      this.lf.register(edgeCustom);
      this.lf.render();
      this.lf.extension.menu.setMenuConfig({
        nodeMenu: [
          {
            text: "复制",
            callback(node) {
              that.lf.cloneNode(node.id);
            },
          },
          {
            text: "删除",
            callback(node) {
              that.lf.deleteNode(node.id);
            },
          },
        ],
        edgeMenu: [
          {
            text: "删除",
            callback(edge) {
              that.lf.deleteEdge(edge.id);
            },
          },
        ],
        graphMenu: [],
      });
      this.lf.extension.dndPanel.setPatternItems(this.flowNodes);
      this.lf.on("node:click", (data) => {
        if (data.data.type == "bpmn:userTask") this.setProcessHandle(data);
      });
      this.lf.on("edge:click", ({ data }) => {
        const turboData = this.lf.getGraphData();
        const { nodes } = this.lf.adapterIn(turboData);
        const node = nodes.find((item) => item.id == data.sourceNodeId);
        if (node.type == "bpmn:exclusiveGateway") this.setEdgeHandle(data);
      });
    },
    initHandle() {
      const column = this.$findByProperty(
        this.popupList,
        "id",
        "craftRouteType"
      );
      this.$set(column, "list", this.workOrdTypeList);
      if (this.operaType == "add") {
        this.formData = {};
      } else {
        const {
          code,
          activeTime,
          expireTime,
          typeCode,
          version,
          name,
          remark,
        } = this.detailData;
        this.formData = {
          craftRouteCode: this.operaType == "copy" ? "" : code,
          craftRouteName: name,
          craftRouteType: typeCode,
          craftRouteVersion: version,
          activeTime: activeTime,
          inactiveTime: expireTime,
          craftRouteRemark: remark,
        };
      }
    },
    initLfHandle() {
      this.createLf();
      if (this.operaType != "add") {
        const flowTurboData = JSON.parse(this.detailData.flowModel);
        const flowLogicData = this.lf.adapterIn(flowTurboData);
        const { nodes, edges } = flowLogicData;
        this.lf.renderRawData({
          nodes,
          edges,
        });
      }
    },
    closeHanlde() {
      this.$emit("input", false);
    },
    createFlowHandle(params) {
      createFlow(params).then((res) => {
        if (res.data.code != 200) return this.$message.error(res.data.msg);
        this.$message.success(this.$t("msg.success"));
        this.$emit("input", false);
        this.$emit("confrim");
      });
    },
    changeLoadLabel(val) {
      this.loadLableObj = val;
    },
    confrimHandle() {
      let flag = this.$refs.form.validateHandle();
      if (!flag) return;
      if (this.formObj.inactiveTime) {
        this.formObj.inactiveTime =
          this.formObj.inactiveTime.split(" ")[0] + " " + "23:59:59";
      }
      if (
        new Date(this.formObj.inactiveTime) < new Date(this.formObj.activeTime)
      )
        return this.$message.warning("失效日期需大于启动日期");
      const turboData = this.lf.getGraphData();
      const { nodes, edges } = this.lf.adapterIn(turboData);
      if (!nodes.length && !edges.length)
        return this.$message.warning("工艺路线不能为空");
      // 校验节点
      const taskList = nodes.filter((item) => item.type == "bpmn:userTask");
      taskList.forEach((item) => {
        let properties = item.properties;
        let errorFlag =
          !properties.processId ||
          !properties.processStep ||
          !properties.processType;
        this.$set(properties, "customError", errorFlag);
        this.lf.setProperties(item.id, properties);
      });
      //校验边
      edges.forEach((item) => {
        const node = nodes.find((val) => val.id == item.sourceNodeId);
        if (node.type == "bpmn:exclusiveGateway") {
          let properties = item.properties;
          let errorFlag = !properties.conditionsequenceflow;
          this.$set(properties, "customError", errorFlag);
          this.lf.setProperties(item.id, properties);
        }
      });
      if (
        edges.some((item) => item.properties.customError) ||
        taskList.some((item) => item.properties.customError)
      )
        return this.$message.warning("请完善工艺路线配置");
      // 校验是否有重复节点
      const idCount = {};
      taskList.forEach((obj) => {
        idCount[obj.properties.processStep] =
          (idCount[obj.properties.processStep] || 0) + 1;
      });
      taskList.forEach((item) => {
        let properties = item.properties;
        let errorFlag = idCount[properties.processStep] > 1;
        this.$set(properties, "customError", errorFlag);
        this.lf.setProperties(item.id, properties);
      });
      if (taskList.some((item) => item.properties.customError))
        return this.$message.warning("存在相同工序步骤，请重新编辑");
      let graphData = this.lf.getGraphData();
      let params = {
        flowModel: JSON.stringify(graphData),
        craftRouteId:
          this.operaType == "flowEdit" ? this.detailData.id : undefined,
        ...this.formObj,
      };
      this.createFlowHandle(params);
    },
    confrimProductHandle() {
      const turboData = this.lf.getGraphData();
      const { nodes } = this.lf.adapterIn(turboData);
      if (
        nodes.some(
          (item) =>
            item.properties.processStep == this.proFormObj.processStep &&
            item.id != this.proFormData.id
        )
      )
        return this.$message.warning("当前工序步骤已存在，请重新输入");
      let propertiesObj = {
        processName: this.loadLableObj["processId"],
        customError: false,
        ...this.proFormObj,
      };
      const currentNode = this.lf.getNodeDataById(this.proFormData.id);
      this.lf.setProperties(this.proFormData.id, propertiesObj);
      const flowItem = this.lf.getNodeModelById(this.proFormData.id);
      flowItem.updateText(this.loadLableObj["processId"]);
      this.isShowEdit = false;
      const res = this.lf.adapterIn(this.lf.getGraphData());
      const fList = res.nodes.filter(
        (item) =>
          item.properties.processStep == currentNode.properties.processStep &&
          item.properties.processStep
      );
      if (fList.length == 1) {
        let propertiesObj = {
          ...fList[0].properties,
          customError: false,
        };
        this.lf.setProperties(fList[0].id, propertiesObj);
      }
    },
    setProcessHandle(data) {
      const col = this.$findByProperty(this.proPopupList, "id", "processId");
      col.selectedLabel = data.data.properties.processName;
      this.proFormData = {
        id: data.data.id,
        ...data.data.properties,
      };
      this.isShowEdit = true;
    },
    setEdgeHandle(data) {
      if (!data.properties.conditionsequenceflow) {
        this.edgeFormData = {
          id: data.id,
          conditionsequenceflow: `status.equals("10")`,
          collectResult: 1,
          defaultConditions: "true",
        };
        this.lf.setProperties(data.id, this.edgeFormData);
      } else {
        this.edgeFormData = {
          id: data.id,
          ...data.properties,
        };
      }
      this.isShowEdgeEdit = true;
    },
  },
};
</script>

<style lang="scss" scoped>
.route-flow {
  height: 464px;
}
</style>
